use std::{time::Duration};

use tauri::{Window};
use tokio::sync::Mutex;

use crate::error::{AppErr, static_msg};

use self::{ctrl::CtrlConn, state::StateConn, ctrl_proto::CtrlProto};


mod ctrl;
mod state;
mod ctrl_proto;
mod state_proto;

pub const CTRL_ADDR: &'static str = "192.168.58.2:8080";
pub const STATE_ADDR: &'static str = "192.168.58.2:8083";

pub const CONNECT_DURATION: Duration = Duration::from_millis(500);

pub const STATE_EVENT: &'static str = "state_resp";

pub struct RobotConn {

    ctrl: CtrlConn,
    state: StateConn,
}

static CONN: Mutex<Option<RobotConn>> = Mutex::const_new(None);

#[tauri::command]
pub async fn is_connect() -> bool {
    CONN.lock().await.is_some()
}

#[tauri::command]
pub async fn connect(window: Window) -> Result<(), AppErr> {
    println!("开始连接");
    let mut conn = CONN.lock().await;

    let ctrl = CtrlConn::connect().await?;
    let state = StateConn::connect(window).await?;

    let ctrl = RobotConn {
        ctrl,
        state
    };
    
    *conn = Some( ctrl );

    Ok(())
}

#[tauri::command]
pub async fn disconnect() {
    let mut conn = CONN.lock().await;
    conn.as_ref()
    .and_then(|v| {
        v.state.exit();
        Some(())
    });
    *conn = None;
}

#[tauri::command]
pub async fn request(cmd_code: u32, name: String, args: Vec<String>) -> Result<CtrlProto, AppErr> {
    let resp = CONN
        .lock()
        .await
        .as_mut()
        .ok_or(static_msg("没有建立连接"))?
        .ctrl
        .request(cmd_code, &name, &args).await?;
    Ok(resp)
}
